package bultin;

import javax.swing.JComponent;
import javax.swing.JOptionPane;

import pseudo_ASH.PseudoMain;
import pseudo_ASH.RightTabPane;

import code.ObjectC;
import code.TokenType;
import code.Variable;
import code.Variable.varType;

import com.sydwell.service.ArrayPlus;
import com.sydwell.service.Helper;


class System_Bi extends BIClass {


	public System_Bi() {
		super("System");
		this.addStatic(new Random());
		this.addStatic(new RadioGroup());
		this.addStatic(new HasValue());
		this.addStatic(new GetType());
		this.addStatic(new ConvertTo());
		this.addStatic(new PromptForInt());
		this.addStatic(new PromptForReal());
		this.addStatic(new PromptForString());
		this.addStatic(new ClearOutput());
		//this.addStatic(new Delay()); this must be implemented thanks to Shannon Williams
	}

	class Random extends BuiltinMethod {
		public Random() {
			super("random");
			super.addParameter(varType.INTEGER);
			super.setReturnType(varType.INTEGER);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> arrayPlus) {
			//Helper.debug("Still to do "+ arrayPlus.get(0).hasLiteralValue(), true);
			int range = arrayPlus.get(0).getTokenVariable().getIntValue();
			range = (int)(Math.random() * range);
			returnVariable.setValue(range);
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			//time = (int) (Math.random() * 20);
		//	Helper.debug("target " + target, true);
			String out = arguments.get(0) + " = (int) (Math.random() * " + target + ")";

			out = out.replace(";", "");
			out = out.replace("\r", "");
			out = out.replace("\n", "");
			return out;
		}

		@Override
		public String information() {
			String out =  "Returns a random integer";
			out += "\nThe integer will be in the range of zero to the supplied parameter" ;
			out += "\nUsage: " ;
			out += "System.random(<supplied>)";
			return out;
		}
	}
	class RadioGroup extends BuiltinMethod {
		public RadioGroup() {
			super("radioGroup");
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> arrayPlus) {
			//newRadioGroup("" + arrayPlus.get(0));
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO Auto-generated method stub
			return "Not Yet Implemented";
		}

		@Override
		public String information() {
			String out =  "a special flag that indicates that new group of radiobuttons are created";
			out += "\nUsage: " ;
			out += "System.radioGroup()";
			return out;
		}
	}
	class HasValue extends BuiltinMethod {
		public HasValue() {
			super("hasValue");
			super.addParameter(varType.ANY_TYPE);
			super.setReturnType(varType.BOOLEAN);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> arrayPlus) {
			Variable range = arrayPlus.get(0).getTokenVariable();
			boolean bool = !range.getType().equalVar(varType.ANY_TYPE);
			returnVariable.setAndConvert("" + bool);
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO time = System.hasValue(chip)
			String out = "";
			if (target.getTokenVariable().getType().equalVar(varType.OBJECT)) {
				out =  arguments.get(0) + "=(" + target + "== null)";
			} else {
				out = arguments.get(0) + "= true";
			}
			//String out =

			out = out.replace(";", "");
			out = out.replace("\r", "");
			out = out.replace("\n", "");
			return out;
		}

		@Override
		public String information() {
			String out =  "Will return true if the supplied variable has a value";
			out += "\nUsage: " ;
			out += "System.hasValue(<supplied>)";
			return out;
		}
	}
	
	class GetType extends BuiltinMethod {
		public GetType() {
			super("getType");
			super.addParameter(varType.ANY_TYPE);
			super.setReturnType(varType.STRING);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> arrayPlus) {
			Variable range = arrayPlus.get(0).getTokenVariable();
			returnVariable.setAndConvert("" + range.getType());
			return returnVariable;
		}

		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			varType vt = arguments.get(0).getTokenVariable().getType();
			return vt.toString();
		}

		@Override
		public String information() {
			String out = "Returns the data type of the supplied variable";
			out += "\nReturned value will be in the form of a String" ;
			out += "\nUsage: " ;
			out += "System.getType(<supplied>)"; 
			return out;
		}
	}
	
	
	class ConvertTo extends BuiltinMethod {
		public ConvertTo() {
			super("convertTo");
			// The variable
			super.addParameter(varType.ANY_TYPE);
			super.addParameter(varType.STRING);
			// What to convert to
			super.setReturnType(varType.ANY_TYPE);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> aruguments) {
			Variable theVar = aruguments.get(0).getTokenVariable();
			varType theType = varType.valueOf(aruguments.get(1).getTokenText());
			returnVariable.setValue(theVar);
			returnVariable.setType(theType);
			return returnVariable;
		}

		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO Auto-generated method stub
			return "Not Yet Implemented";
		}

		@Override
		public String information() {
			String out = "Converts the supplied value to the requested type";
			out += "\nValid request types are Integer, Real, Boolean and String " ;
			out += "\nUsage: " ;
			out += "System.convertTo(<supplied>, <requested type>)"; 
			return out;
		}
	}
	
	/**
	 * Implementation details for this method
	 * 
	 * @author sydwell
	 *
	 */
	class PromptForInt extends BuiltinMethod {
		public PromptForInt() {
			super("promptForInt");
			super.addParameter(varType.STRING);
			super.setReturnType(varType.INTEGER);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> aruguments) {
			String theVar = aruguments.get(0).getStrEq();
			boolean done = false;
			int out = 0;
			while (!done) {
				String var = JOptionPane.showInputDialog(PseudoMain.mainPane, theVar);
				try {
					out = Integer.parseInt(var);
					done = true;
				} catch (NumberFormatException e) {
					done = false;
				}		
			}
			returnVariable.setValue(out);
			returnVariable.setType(varType.INTEGER);
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO Auto-generated method stub
			return "Not Yet Implemented";
		}

		@Override
		public String information() {
			String out = "Prompts the user for a integer value";
			out += "\nUsage: " ;
			out += "System.promptForInt()";
			out += "\nWhere <supplied> will be the message displayed";
			out += "\nNote the dialog will repeatedly be displayed until a integer value has been entered";
			return out;
		}
	}
	
	/**
	 * Implementation details for this method
	 * 
	 * @author sydwell
	 *
	 */
	class PromptForReal extends BuiltinMethod {
		public PromptForReal() {
			super("promptForReal");
			// The variable
			super.addParameter(varType.STRING);
			// What to convert to
			super.setReturnType(varType.REAL);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> aruguments) {
			String theVar = aruguments.get(0).getStrEq();
			boolean done = false;
			double out = 0;
			while (!done) {
				String var = JOptionPane.showInputDialog(PseudoMain.mainPane, theVar);
				try {
					out = Double.parseDouble(var);
					done = true;
				} catch (NumberFormatException e) {
					done = false;
				}		
			}
			returnVariable.setValue(out);
			returnVariable.setType(varType.REAL);
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO Auto-generated method stub
			if (arguments == null) {
				Helper.debug(" no args ");
			}
			return "Not Yet Implemented";
		}

		@Override
		public String information() {
			String out = "Prompts the user for a real value";
			out += "\nUsage: " ;
			out += "System.promptForReal(<supplied>)"; 
			out += "\nWhere <supplied> will be the message displayed";
			out += "\nNote the dialog will repeatedly be displayed until a real value has been entered";
			return out;
		}
	}
	
	/**
	 * Implementation details for this method
	 * 
	 * @author sydwell
	 *
	 */
	class PromptForString extends BuiltinMethod {
		public PromptForString() {
			super("promptForString");
			// The variable
			super.addParameter(varType.STRING);
			// What to convert to
			super.setReturnType(varType.STRING);
		}

		@Override
		public Variable excuteMethod(ObjectC nop, ArrayPlus<TokenType> aruguments) {
			String theVar = aruguments.get(0).getStrEq();
			String var = JOptionPane.showInputDialog(PseudoMain.mainPane, theVar);
			returnVariable.setValue(var);
			returnVariable.setType(varType.STRING);
			return returnVariable;
		}
		
		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments, TokenType target) {
			// TODO Auto-generated method stub
			if (arguments == null) {
				Helper.debug(" no args ");
			}
			return "Not Yet Implemented";
		}

		@Override
		public String information() {
			String out = "Prompts the user for a String";
			out += "\nUsage:" ;
			out += " System.promptForString(<supplied>)";
			out += "\nWhere <supplied> will be the message displayed to the user";
			out += "\nAll types of data supplied by the user will be converted to a String";
			return out;
		}
	}
	
	@Override
	public JComponent makeJavaComp(String theInstanceName,
			ArrayPlus<TokenType> arguments) {
		// TODO D
		return null;
	}
	
	@Override
	public String getJavaClassName() {
		return "System";
	}
	
	/**
	 * Implementation details for this method
	 * 
	 * @author sydwell
	 *
	 */
	class ClearOutput extends BuiltinMethod {
		public ClearOutput() {
			super("clearOutput");
			// The variable
			//super.addParameter(varType.ANY_TYPE);
			// What to convert to
			//super.setReturnType(varType.STRING);
		}

		@Override
		public Variable excuteMethod(ObjectC object2operateOn,
				ArrayPlus<TokenType> arrayPlus)  {
				RightTabPane.clearDisplay();
			return null;
		}

		@Override
		public String convert2Java(ArrayPlus<TokenType> arguments,
				TokenType target) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public String information() {
			String out = "Clears the output window";
			out += "\nUsage: " ;
			out += "System.clear()"; 
			return out;
		}
	}
}
